﻿using System;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;

using log4net;
using log4net.Config;

namespace MonPocGarage.Common.Logging
{
    /// <summary>
    /// Logging Handler for MonPoc Garage
    /// </summary>
    public static class LogHandler
    {
        private static readonly ILog m_Logger = LogManager.GetLogger(ConfigurationManager.AppSettings["LoggerName"] ?? Assembly.GetEntryAssembly().FullName);
        private static bool m_IsInitialized;

        /// <summary>
        /// Writes a log message from the logger in AppSettings["LoggerName"] to the configured log4net Appender
        /// </summary>
        /// <param name="message">The message to write to the log</param>
        /// <param name="level">Message level of the message</param>
        public static void LogMessage(string message, MessageLevel level)
        {
            if (!m_IsInitialized)
            {
                InitializeLogging();
                if (!m_IsInitialized)
                {
                    return;
                }
            }
            switch (level)
            {
#if DEBUG
                case MessageLevel.DEBUG:
                    m_Logger.Debug(message);
                    break;
#endif
                case MessageLevel.ERROR:
                    m_Logger.Error(message);
                    break;
                case MessageLevel.FATAL:
                    m_Logger.Fatal(message);
                    break;
                case MessageLevel.INFO:
                    m_Logger.Info(message);
                    break;
                case MessageLevel.WARN:
                    m_Logger.Warn(message);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Writes a log message from a named Logger to the configured log4net Appender
        /// </summary>
        /// <param name="message">The message to write to the log</param>
        /// <param name="level">Message level of the message</param>
        /// <param name="loggerName">Logger name to write the message as</param>
        public static void LogMessage(string message, MessageLevel level, string loggerName)
        {
            if (!m_IsInitialized)
            {
                InitializeLogging();
            }
            ILog singletonLogger = LogManager.GetLogger(loggerName);
            switch (level)
            {
#if DEBUG
                case MessageLevel.DEBUG:
                    singletonLogger.Debug(message);
                    break;
#endif
                case MessageLevel.ERROR:
                    singletonLogger.Error(message);
                    break;
                case MessageLevel.FATAL:
                    singletonLogger.Fatal(message);
                    break;
                case MessageLevel.INFO:
                    singletonLogger.Info(message);
                    break;
                case MessageLevel.WARN:
                    singletonLogger.Warn(message);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Writes an exception message from the logger in AppSettings["LoggerName"] to the configured log4net Appender
        /// </summary>
        /// <param name="message">The message to write to the log</param>
        /// <param name="ex">The exception message to be recorded</param>
        /// <param name="level">Message level of the message</param>        
        public static void LogException(string message, Exception ex, MessageLevel level)
        {
            if (!m_IsInitialized)
            {
                InitializeLogging();
            }
            switch (level)
            {
#if DEBUG
                case MessageLevel.DEBUG:
                    m_Logger.Debug(message, ex);
                    break;
#endif
                case MessageLevel.ERROR:
                    m_Logger.Error(message, ex);
                    break;
                case MessageLevel.FATAL:
                    m_Logger.Fatal(message, ex);
                    break;
                case MessageLevel.INFO:
                    m_Logger.Info(message, ex);
                    break;
                case MessageLevel.WARN:
                    m_Logger.Warn(message, ex);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Writes an exception message from "loggerName" to the configured log4net Appender
        /// </summary>
        /// <param name="message">The message to write to the log</param>
        /// <param name="ex">The exception message to be recorded</param>
        /// <param name="level">Message level of the message</param> 
        /// <param name="loggerName">Logger name to write the message as</param>
        public static void LogException(string message, Exception ex, MessageLevel level, string loggerName)
        {
            if (!m_IsInitialized)
            {
                InitializeLogging();
            }
            ILog singletonLogger = LogManager.GetLogger(loggerName);
            switch (level)
            {
#if DEBUG
                case MessageLevel.DEBUG:
                    singletonLogger.Debug(message, ex);
                    break;
#endif
                case MessageLevel.ERROR:
                    singletonLogger.Error(message, ex);
                    break;
                case MessageLevel.FATAL:
                    singletonLogger.Fatal(message, ex);
                    break;
                case MessageLevel.INFO:
                    singletonLogger.Info(message, ex);
                    break;
                case MessageLevel.WARN:
                    singletonLogger.Warn(message, ex);
                    break;
                default:
                    break;
            }
        }

        private static void InitializeLogging()
        {
            try
            {
                XmlConfigurator.Configure();
                m_IsInitialized = true;
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("Application Error",
                                    "Unable to initialize logging for " + Assembly.GetCallingAssembly().FullName + ". Exception: " + ex.StackTrace,
                                    EventLogEntryType.Error, 1000);
                m_IsInitialized = false;
            }
        }
    }
}
